<script setup lang="ts">
import { type Component, h, onMounted, ref, renderSlot, useAttrs, useSlots, type VNodeChild, watch } from 'vue';


import { createReusableTemplate } from '@vueuse/core';
import { type ButtonProps, NButton, type PopoverProps, type TooltipProps } from 'naive-ui';

defineOptions({
  name: 'WAction',
  inheritAttrs: false,
});
const props = withDefaults(defineProps<Props>(), {
  type: 'default',
  iconPlacement: 'left',
  tooltipPlacement: 'top',
  disabled: false,
  round: false,
  circle: false,
  text: false,
  size: 'medium',
});
const emit = defineEmits<Emits>();
defineSlots<{
  default: () => VNodeChild;
  icon: () => VNodeChild;
  label: () => VNodeChild;
  title: () => VNodeChild;
  tooltip: () => VNodeChild;
  trigger: () => VNodeChild;
}>();
type ConfirmType = {
  done: (bool: boolean) => void;
};
interface Emits {
  (e: 'cancel'): void;
  (e: 'click'): void;
  (e: 'mouseover'): void;
  (e: 'confirm', props: ConfirmType): void;
}
interface Props {
  buttonProps?: ButtonProps;
  circle?: boolean;
  disabled?: boolean;
  drawerProps?: DrawerProps;
  icon?: Component | Function | string;
  iconPlacement?: 'left' | 'right';
  iconProps?: Record<string, any>;
  label?: string;
  modalProps?: ModalProps;
  popoverProps?: PopoverProps;
  round?: boolean;
  size?: 'large' | 'medium' | 'small' | 'tiny';
  text?: boolean;
  title?: string;
  tooltip?: string;
  tooltipPlacement?: 'bottom' | 'bottom-end' | 'bottom-start' | 'left' | 'left-end' | 'left-start' | 'right' | 'right-end' | 'right-start' | 'top' | 'top-end' | 'top-start';
  tooltipProps?: TooltipProps;
  /**
   * @param type 渲染类型
   */
  type?: 'api' | 'default' | 'drawer' | 'modal' | 'popover';
}
const show = defineModel('show', {
  default: false,
});
const attrs = useAttrs();
const slots = useSlots();
const isReturnBool = ref(true);

const done = (bool: boolean) => {
  isReturnBool.value = bool;
};

const [BaseModal, modalApi] = useVbenModal({
  draggable: true,
  closeOnClickModal: false,
  onCancel() {
    toggleShow(false);
    emit('cancel');
  },
  onConfirm() {
    emit('confirm', { done });
    if (isReturnBool.value) {
      modalApi.close();
    }
  },
  onOpenChange(isOpen: boolean) {
    toggleShow(isOpen);
  },
});

const [BaseDrawer, drawerApi] = useVbenDrawer({
  closeOnClickModal: false,
  title: props.title,
  onCancel() {
    toggleShow(false);
  },
  onConfirm() {
    emit('confirm', { done });
    if (isReturnBool.value) {
      drawerApi.close();
    }
  },
  onOpenChange(isOpen: boolean) {
    toggleShow(isOpen);
  },
});

const initRender = () => {
  if (props.type === 'drawer') {
    show.value ? drawerApi.open() : drawerApi.close();
  } else if (props.type === 'modal') {
    show.value ? modalApi.open() : modalApi.close();
  }
};

watch(show, () => {
  initRender();
});

onMounted(() => {
  initRender();
});

const toggleShow = (bool: boolean) => {
  show.value = bool;
};

const onClick = () => {
  if (['drawer', 'modal'].includes(props.type)) {
    toggleShow(true);
  }
  emit('click');
};

const onMouseover = () => {
  emit('mouseover');
};

const btnNode = () => {
  const btnProps: { [index: string]: any } & ButtonProps = {
    secondary: true,
    strong: true,
    round: props.round,
    disabled: props.disabled,
    circle: props.circle,
    text: props.text,
    iconPlacement: props.iconPlacement,
    onClick,
    onMouseover,
    ...props.buttonProps,
    ...attrs,
  };
  const btnSlots: Record<string, any> = {
    default: () => (slots?.label ? renderSlot(slots, 'label') : props.type === 'default' ? props.label || renderSlot(slots, 'default') : props.label),
  };
  if (props.icon || slots?.icon) {
    btnSlots.icon = () => (slots?.icon ? renderSlot(slots, 'icon') : h(SvgIcon, { icon: props.icon, ...props.iconProps }));
  }
  return h(NButton, btnProps, btnSlots);
};

const [DefineTitle, ReuseTitle] = createReusableTemplate();
const [DefineTrigger, ReuseTrigger] = createReusableTemplate();

const exposed = {
  props,
  show,
  modalApi,
  drawerApi,
  toggleShow,
  onClick,
};

defineExpose(exposed);
</script>

<template>
  <DefineTitle>
    <slot name="title">
      <n-text class="text-xl font-bold"> {{ title }} </n-text>
    </slot>
  </DefineTitle>
  <DefineTrigger>
    <div class="w-action">
      <slot name="trigger" v-bind="exposed"> <component :is="btnNode()" /></slot>
    </div>
  </DefineTrigger>
  <template v-if="type === 'modal'">
    <BaseModal v-bind="modalProps">
      <template #title><ReuseTitle /></template>
      <slot></slot>
    </BaseModal>
  </template>
  <template v-if="type === 'drawer'">
    <BaseDrawer v-bind="drawerProps">
      <template #title><ReuseTitle /></template>
      <slot></slot>
    </BaseDrawer>
  </template>
  <template v-if="type === 'popover'">
    <n-popover v-bind="popoverProps">
      <template #trigger>
        <ReuseTrigger />
      </template>
      <slot></slot>
    </n-popover>
  </template>
  <template v-else>
    <n-tooltip v-if="tooltip" :placement="tooltipPlacement" v-bind="tooltipProps">
      <template #trigger>
        <ReuseTrigger />
      </template>
      <slot name="tooltip">{{ tooltip }}</slot>
    </n-tooltip>
    <ReuseTrigger v-else />
  </template>
</template>

<style scoped>
.w-action {
  display: inline-block;
}
</style>
